home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 7 / FM Towns Free Software Collection 7.iso / taropyon / zmodem / src / sz.c < prev    next >
C/C++ Source or Header  |  1993-11-30  |  45KB  |  2,123 lines

  1. #define    __TOWNS__
  2. //#define    DEBUG
  3. #define VERSION "3.11 02-26-91"
  4. #define PUBDIR "/usr/spool/uucppublic"
  5.  
  6. #ifdef    __TOWNS__
  7. #    define    TXBSIZE    16384
  8. #    define    READCHECK
  9. #endif
  10.  
  11. /*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384  -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
  12.  
  13. <-xtx-*> cc -Osal -DTXBSIZE=32768  -DSV sz.c -lx -o $B/sz; size $B/sz
  14.  
  15.  ****************************************************************************
  16.  *
  17.  * sz.c By Chuck Forsberg,  Omen Technology INC
  18.  *
  19.  ****************************************************************************
  20.  *
  21.  * Typical Unix/Xenix/Clone compiles:
  22.  *
  23.  *        cc -O sz.c -o sz                USG (SYS III/V) Unix
  24.  *        cc -O -DSV sz.c -o sz            Sys V Release 2 with non-blocking input
  25.  *                                        Define to allow reverse channel checking
  26.  *        cc -O -DV7  sz.c -o sz            Unix Version 7, 2.8 - 4.3 BSD
  27.  *
  28.  *        cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz        Classic Xenix
  29.  *
  30.  *        ln sz sb                        **** All versions ****
  31.  *        ln sz sx                        **** All versions ****
  32.  *
  33.  ****************************************************************************
  34.  ****************************************************************************
  35.  *
  36.  *
  37.  * A program for Unix to send files and commands to computers running
  38.  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
  39.  *
  40.  *  Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
  41.  *
  42.  *  USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
  43.  *
  44.  * 
  45.  *        This version implements numerous enhancements including ZMODEM
  46.  *        Run Length Encoding and variable length headers.  These
  47.  *        features were not funded by the original Telenet development
  48.  *        contract.
  49.  * 
  50.  * This software may be freely used for non commercial and
  51.  * educational (didactic only) purposes.  This software may also
  52.  * be freely used to support file transfer operations to or from
  53.  * licensed Omen Technology products.  Any programs which use
  54.  * part or all of this software must be provided in source form
  55.  * with this notice intact except by written permission from Omen
  56.  * Technology Incorporated.
  57.  * 
  58.  * Use of this software for commercial or administrative purposes
  59.  * except when exclusively limited to interfacing Omen Technology
  60.  * products requires a per port license payment of $20.00 US per
  61.  * port (less in quantity).  Use of this code by inclusion,
  62.  * decompilation, reverse engineering or any other means
  63.  * constitutes agreement to these conditions and acceptance of
  64.  * liability to license the materials and payment of reasonable
  65.  * legal costs necessary to enforce this license agreement.
  66.  *
  67.  *
  68.  *                Omen Technology Inc                FAX: 503-621-3745
  69.  *                Post Office Box 4681
  70.  *                Portland OR 97208
  71.  *
  72.  *        This code is made available in the hope it will be useful,
  73.  *        BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  74.  *        DAMAGES OF ANY KIND.
  75.  */
  76.  
  77.  
  78. #ifndef    __TOWNS__
  79. char       *substr(), *getenv();
  80. #endif
  81.  
  82. #define LOGFILE "/tmp/szlog"
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86. #include <signal.h>
  87. #include <stat.h>
  88. #include <setjmp.h>
  89. #include <ctype.h>
  90. #include <errno.h>
  91.  
  92. #ifdef    __TOWNS__
  93. #    include    <stdarg.h>
  94. #    include    <process.h>
  95. #    include    <time.h>
  96. #    include    <io.h>
  97. #    include    <splib.h>
  98. #    include    <fslib.h>
  99.  
  100. #    include    "usrlib.h"
  101. #    include    "rsctrl.h"
  102. #    include    "flib.h"
  103. #    include    "msgdat.h"
  104.  
  105. #    ifdef    __HIGHC__
  106. #        pragma    On(Align_labels);
  107. #    endif
  108.  
  109.     extern    int    RsPort;
  110. #    define    _FSTAT_IGN
  111. #endif
  112.  
  113. #include    "prot.h"
  114. #include    "sz.h"
  115.  
  116. extern    int        errno;
  117. #define    STATIC    static
  118.  
  119. #define HOWMANY 2
  120. STATIC int        Zmodem = 0;         /* ZMODEM protocol requested by receiver */
  121. unsigned        Baudrate = 4800;    /* Default, set by first mode() call */
  122. unsigned        Effbaud = 4800;
  123. STATIC unsigned Txwindow;            /* Control the size of the transmitted window */
  124. STATIC unsigned Txwspac;            /* Spacing between zcrcq requests */
  125. STATIC unsigned Txwcnt;             /* Counter used to space ack requests */
  126. STATIC long        Lrxpos;             /* Receiver's last reported offset */
  127. STATIC int        errors;
  128. char            endmsg[80] = {0};    /* Possible message to display on exit */
  129.  
  130. #include "rbsb.c"                    /* most of the system dependent stuff here */
  131. #include "crctab.c"
  132.  
  133. STATIC int    Filesleft;
  134. STATIC long    Totalleft;
  135.  
  136. /*
  137.  * Attention string to be executed by receiver to interrupt streaming data
  138.  *  when an error is detected.  A pause (0336) may be needed before the
  139.  *  ^C (03) or after it.
  140.  */
  141. #ifdef READCHECK
  142.     STATIC char Myattn[] = {0};
  143. #else
  144. #    ifdef USG
  145.         STATIC char Myattn[] = {03, 0336, 0};
  146. #    endif
  147. #endif
  148.  
  149. FILE       *in;
  150. char       *infile;    /* High C stat() */
  151.  
  152. #ifdef BADSEEK
  153. STATIC int    Canseek = 0;    /* 1: Can seek 0: only rewind -1: neither (pipe) */
  154. #    ifndef TXBSIZE
  155. #        define TXBSIZE 16384    /* Must be power of two, < MAXINT */
  156. #    endif
  157. #else
  158. STATIC int    Canseek = 1;        /* 1: Can seek 0: only rewind -1: neither (pipe) */
  159. #endif
  160.  
  161. #ifdef TXBSIZE
  162. #define TXBMASK (TXBSIZE-1)
  163. STATIC char Txb[TXBSIZE];        /* Circular buffer for file reads */
  164. STATIC char *txbuf = Txb;        /* Pointer to current file segment */
  165. #else
  166. STATIC char txbuf[1024];
  167. #endif
  168. STATIC long vpos = 0;            /* Number of bytes read from file */
  169.  
  170. STATIC char Lastrx;
  171. STATIC char Crcflg;
  172. #ifdef    DEBUG
  173. STATIC int    Verbose = 5;
  174. #else
  175. STATIC int    Verbose = 0;
  176. #endif
  177. STATIC int    Modem2 = 0;         /* XMODEM Protocol - don't send pathnames */
  178. STATIC int    Restricted = 0;     /* restricted; no /.. or ../ in filenames */
  179. STATIC int    Quiet = 0;            /* overrides logic that would otherwise set verbose */
  180. STATIC int    Ascii = 0;            /* Add CR's for brain damaged programs */
  181. STATIC int    Fullname = 0;        /* transmit full pathname */
  182. STATIC int    Unlinkafter = 0;    /* Unlink file after it is sent */
  183. STATIC int    Dottoslash = 0;     /* Change foo.bar.baz to foo/bar/baz */
  184. STATIC int    firstsec;
  185. STATIC int    errcnt = 0;         /* number of files unreadable */
  186. STATIC int    blklen = 128;        /* length of transmitted records */
  187. STATIC int    Optiong;            /* Let it rip no wait for sector ACK's */
  188. STATIC int    Eofseen;            /* EOF seen on input set by zfilbuf */
  189. STATIC int    BEofseen;            /* EOF seen on input set by fooseek */
  190. STATIC int    Totsecs;            /* total number of sectors this file */
  191. STATIC int    Filcnt = 0;         /* count of number of files opened */
  192. STATIC int    Lfseen = 0;
  193. STATIC unsigned Rxbuflen = 16384;    /* Receiver's max buffer length */
  194. STATIC int    Tframlen = 0;        /* Override for tx frame length */
  195. STATIC int    blkopt = 0;         /* Override value for zmodem blklen */
  196. STATIC int    Rxflags = 0;
  197. STATIC long bytcnt;
  198. STATIC int    Wantfcs32 = TRUE;    /* want to send 32 bit FCS */
  199. STATIC char Lzconv;             /* Local ZMODEM file conversion request */
  200. STATIC char Lzmanag;            /* Local ZMODEM file management request */
  201. STATIC int    Lskipnocor;
  202. STATIC char Lztrans;
  203. STATIC int    Command;            /* Send a command, then exit. */
  204. STATIC char *Cmdstr;            /* Pointer to the command string */
  205. STATIC int    Cmdtries = 11;
  206. STATIC int    Cmdack1;            /* Rx ACKs command, then do it */
  207. STATIC int    Exitcode;
  208. STATIC int    Test = 0;            /* 1= Force receiver to send Attn, etc with qbf.
  209.                                    2= Character transparency test */
  210. STATIC char *qbf = "The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
  211. STATIC long Lastsync = 0;        /* Last offset to which we got a ZRPOS */
  212. STATIC int    Beenhereb4 = 0;     /* How many times we've been ZRPOS'd same place */
  213.  
  214. STATIC jmp_buf tohere;            /* For the interrupt on RX timeout */
  215. STATIC jmp_buf intrjmp;         /* For the interrupt on RX CAN */
  216.  
  217. #ifdef XARGSFILE
  218. static    char       *mystrsave(char *s)
  219. {
  220.     register char *p;
  221.     char       *malloc();
  222.  
  223.     if (p = malloc(strlen(s) + 1))
  224.     {
  225.         strcpy(p, s);
  226.         return p;
  227.     }
  228.     USR_fprintf(stderr, "No memory for mystrsave!\n");
  229.     EXIT(1);
  230. }
  231.  
  232. /* Remove (presumably) terminating CR and/or LF from string */
  233. static    void    uncrlf( register char *s )
  234. {
  235.     for (; *s; ++s)
  236.         switch (*s)
  237.         {
  238.             case '\r':
  239.             case '\n':
  240.                 *s = 0;
  241.                 return;
  242.         }
  243. }
  244. #endif
  245.  
  246.  
  247. #ifdef    __TOWNS__
  248.  
  249. void    (*signal_int_func)(int) = SIG_DFL;
  250. extern    int        CtrlX;
  251.  
  252. void    signal_func(int level)
  253. {
  254.     if ( signal_int_func == SIG_ERR )
  255.     {
  256.     } else if ( signal_int_func == SIG_DFL )
  257.     {
  258.         EXIT(3);
  259.     } else if ( signal_int_func == SIG_IGN )
  260.     {
  261.     } else
  262.         (signal_int_func)(level);
  263. }
  264.  
  265. void    my_signal( int mode, void (*func)(int) )
  266. {
  267.     switch ( mode )
  268.     {
  269.         case SIGINT:
  270.             signal_int_func = func;
  271.             break;
  272.     }
  273. }
  274. #define    SIGNAL(_mode,_func)    my_signal(_mode,_func)
  275.  
  276. /* called by signal interrupt or terminate to clean things up */
  277. void    bibi(int n)
  278. {
  279.     SIGNAL(SIGINT, SIG_IGN);
  280.     canit();
  281.     mode(0);    /* restore original tty mode */
  282.     USR_fprintf(stderr, "sz: caught signal %d; exiting\n", n);
  283.     if (n == SIGQUIT)
  284.         EXIT(0);
  285.     if (n == 99)
  286.         USR_fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
  287.     cucheck();
  288.     EXIT(128 + n);
  289. }
  290. /* Called when ZMODEM gets an interrupt (^X) */
  291. void    onintr(int level)
  292. {
  293.     SIGNAL(SIGINT, SIG_IGN);
  294.     CtrlX = FALSE;
  295.     longjmp(intrjmp, -1);
  296. }
  297. #else
  298. /* called by signal interrupt or terminate to clean things up */
  299. void    bibi(int n)
  300. {
  301.     canit();
  302.     mode(0);    /* restore original tty mode */
  303.     USR_fprintf(stderr, "sz: caught signal %d; exiting\n", n);
  304.     if (n == SIGQUIT)
  305.         abort();
  306.     if (n == 99)
  307.         USR_fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
  308.     cucheck();
  309.     EXIT(128 + n);
  310. }
  311. /* Called when ZMODEM gets an interrupt (^X) */
  312. void    onintr(void)
  313. {
  314.     signal(SIGINT, SIG_IGN);
  315.     longjmp(intrjmp, -1);
  316. }
  317. #endif
  318.  
  319.  
  320. STATIC int    Zctlesc;            /* Encode control characters */
  321. STATIC int    Nozmodem = 0;        /* If invoked as "sb" */
  322. STATIC char *Progname = "sz";
  323. STATIC int    Zrwindow = 1400;    /* RX window size (controls garbage count) */
  324. #include "zm.c"
  325.  
  326. #include "zmr.c"
  327.  
  328. #ifdef XARGSFILE
  329. #define XARGSMAX 256
  330. char    *xargv[XARGSMAX + 1];
  331. #endif
  332.  
  333. void    zm_main(int argc, char *argv[])
  334. {
  335.     register char *cp;
  336.     register    npats;
  337.     int         dm;
  338.     char      **patts;
  339. //    static char xXbuf[BUFSIZ];
  340.  
  341. #ifndef    __TOWNS__
  342.     if ((cp = getenv("ZNULLS")) && *cp)
  343.         Znulls = atoi(cp);
  344.     if ((cp = getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
  345.         Restricted = TRUE;
  346. #endif
  347.     from_cu();
  348.     chkinvok(argv[0]);
  349.  
  350.     Rxtimeout = 600;
  351.     npats = 0;
  352.     if (argc < 2)
  353.         usage();
  354. #ifndef    __TOWNS__
  355.     setbuf(stdout, xXbuf);
  356. #endif
  357.     while ( --argc )
  358.     {
  359.         cp = *++argv;
  360.         if (*cp++ == '-' && *cp)
  361.         {
  362.             while (*cp)
  363.             {
  364.                 switch (*cp++)
  365.                 {
  366.                     case '\\':
  367.                         *cp = toupper(*cp);
  368.                         continue;
  369.                     case '+':
  370.                         Lzmanag = ZMAPND;
  371.                         break;
  372. #ifdef CSTOPB
  373.                     case '2':
  374.                         Twostop = TRUE;
  375.                         break;
  376. #endif
  377.                     case 'a':
  378.                         Lzconv = ZCNL;
  379.                         Ascii = TRUE;
  380.                         break;
  381.                     case 'b':
  382.                         Lzconv = ZCBIN;
  383.                         break;
  384.                     case 'C':
  385.                         if (--argc < 1)
  386.                         {
  387.                             usage();
  388.                         }
  389.                         Cmdtries = atoi(*++argv);
  390.                         break;
  391.                     case 'i':
  392.                         Cmdack1 = ZCACK1;
  393.                         /* **** FALL THROUGH TO **** */
  394.                     case 'c':
  395.                         if (--argc != 1)
  396.                         {
  397.                             usage();
  398.                         }
  399.                         Command = TRUE;
  400.                         Cmdstr = *++argv;
  401.                         break;
  402.                     case 'd':
  403.                         ++Dottoslash;
  404.                         /* **** FALL THROUGH TO **** */
  405.                     case 'f':
  406.                         Fullname = TRUE;
  407.                         break;
  408.                     case 'e':
  409.                         Zctlesc = 1;
  410.                         break;
  411.                     case 'k':
  412.                         blklen = 1024;
  413.                         break;
  414.                     case 'L':
  415.                         if (--argc < 1)
  416.                         {
  417.                             usage();
  418.                         }
  419.                         blkopt = atoi(*++argv);
  420.                         if (blkopt < 24 || blkopt > 1024)
  421.                             usage();
  422.                         break;
  423.                     case 'l':
  424.                         if (--argc < 1)
  425.                         {
  426.                             usage();
  427.                         }
  428.                         Tframlen = atoi(*++argv);
  429.                         if (Tframlen < 32 || Tframlen > 1024)
  430.                             usage();
  431.                         break;
  432.                     case 'N':
  433.                         Lzmanag = ZMNEWL;
  434.                         break;
  435.                     case 'n':
  436.                         Lzmanag = ZMNEW;
  437.                         break;
  438.                     case 'o':
  439.                         Wantfcs32 = FALSE;
  440.                         break;
  441.                     case 'p':
  442.                         Lzmanag = ZMPROT;
  443.                         break;
  444.                     case 'r':
  445.                         if (Lzconv == ZCRESUM)
  446.                             Lzmanag = (Lzmanag & ZMMASK) | ZMCRC;
  447.                         Lzconv = ZCRESUM;
  448.                         break;
  449.                     case 'q':
  450.                         Quiet = TRUE;
  451.                         Verbose = 0;
  452.                         break;
  453.                     case 't':
  454.                         if (--argc < 1)
  455.                         {
  456.                             usage();
  457.                         }
  458.                         Rxtimeout = atoi(*++argv);
  459.                         if (Rxtimeout < 10 || Rxtimeout > 1000)
  460.                             usage();
  461.                         break;
  462.                     case 'T':
  463.                         if (++Test > 1)
  464.                         {
  465.                             vfile("test mode");
  466.                             chartest(1);    /* save old tty stat, set raw mode */
  467.                             chartest(2);    /* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
  468.                             mode(0);        /* restore original tty mode */
  469.                             EXIT(0);
  470.                         }
  471.                         break;
  472.                     case 'u':
  473.                         ++Unlinkafter;
  474.                         break;
  475.                     case 'v':
  476.                         ++Verbose;
  477.                         break;
  478.                     case 'w':
  479.                         if (--argc < 1)
  480.                         {
  481.                             usage();
  482.                         }
  483.                         Txwindow = atoi(*++argv);
  484.                         if (Txwindow < 256)
  485.                             Txwindow = 256;
  486.                         Txwindow = (Txwindow / 64) * 64;
  487.                         Txwspac = Txwindow / 4;
  488.                         if (blkopt > Txwspac
  489.                             || (!blkopt && Txwspac < 1024))
  490.                             blkopt = Txwspac;
  491.                         break;
  492.                     case 'X':
  493.                         ++Modem2;
  494.                         break;
  495.                     case 'Y':
  496.                         Lskipnocor = TRUE;
  497.                         /* **** FALLL THROUGH TO **** */
  498.                     case 'y':
  499.                         Lzmanag = ZMCLOB;
  500.                         break;
  501.                     case 'Z':
  502.                     case 'z':
  503.                         Lztrans = ZTRLE;
  504.                         break;
  505.                     default:
  506.                         usage();
  507.                 }
  508.             }
  509.         } else if (!npats && argc > 0)
  510.         {
  511.             if (argv[0][0])
  512.             {
  513.                 npats = argc;
  514.                 patts = argv;
  515.             }
  516.         }
  517.     }
  518.     if (npats < 1 && !Command && !Test)
  519.         usage();
  520. #ifndef    __TOWNS__
  521.     if ( Verbose )
  522.     {
  523.         if ( freopen(LOGFILE, "a", stderr) == NULL )
  524.         {
  525.             printf("Can't open log file %s\n", LOGFILE);
  526.             EXIT(0200);
  527.         }
  528.         setbuf(stderr, NULL);
  529.     }
  530. #endif
  531.     if (Fromcu && !Quiet)
  532.     {
  533.         if (Verbose == 0)
  534.             Verbose = 2;
  535.     }
  536. #ifdef    __TOWNS__
  537.     USR_fprintf(stderr,"\n");
  538.     USR_fprintf(stderr,"sz ver.%s for TownsOS", MAIN_VER);
  539.     USR_fprintf(stderr,"    orignal sz %s\n\n", VERSION);
  540. #else
  541.     vfile("%s %s for %s\n", Progname, VERSION, OS);
  542. #endif
  543.  
  544. #ifdef XARGSFILE
  545.     vfile("npats=%d *patts=%s", npats, *patts);
  546.     if (npats == 1 && !strcmp(XARGSFILE, *patts))
  547.     {
  548.         infile = XARGSFILE;    in = FM_fopen(infile, "rb");    
  549.         if (!in)
  550.         {
  551.             USR_printf(stderr, "Can't open / control file!\n");
  552.             EXIT(2);
  553.         }
  554.         for (npats = 0, argv = patts = xargv; npats < XARGSMAX; ++npats, ++argv)
  555.         {
  556.             if (fgets(txbuf, 1024, in) <= 0)
  557.                 break;
  558.             uncrlf(txbuf);
  559.             *argv = mystrsave(txbuf);
  560.         }
  561.         FM_fclose(in);
  562.     }
  563. #endif
  564.  
  565.     mode(1);    /* save old tty stat, set raw mode */
  566.  
  567. #ifdef    __TOWNS__
  568.     SIGNAL(SIGINT,bibi);
  569. #else
  570.     if (signal(SIGINT, bibi) == SIG_IGN)
  571.     {
  572.         signal(SIGINT, SIG_IGN);
  573.         signal(SIGKILL, SIG_IGN);
  574.     } else
  575.     {
  576.         signal(SIGINT, bibi);
  577.         signal(SIGKILL, bibi);
  578.     }
  579. #ifdef SIGQUIT
  580.     if (!Fromcu)
  581.         signal(SIGQUIT, SIG_IGN);
  582. #endif
  583. #ifdef SIGTERM
  584.     signal(SIGTERM, bibi);
  585. #endif
  586. #endif /* endof ifndef __TOWNS__ */
  587.  
  588.     if (!Modem2)
  589.     {
  590.         if (!Nozmodem)
  591.         {
  592.             RS_puts(RsPort,"rz\r");
  593.         }
  594.         countem(npats, patts);
  595.         if (!Nozmodem)
  596.         {
  597.             stohdr(0L);
  598.             if (Command)
  599.                 Txhdr[ZF0] = ZCOMMAND;
  600.             zshhdr(4, ZRQINIT, Txhdr);
  601.         }
  602.     }
  603.  
  604.     if (Command)
  605.     {
  606.         if (getzrxinit())
  607.         {
  608.             Exitcode = 0200;
  609.             canit();
  610.         } else if (zsendcmd(Cmdstr, 1 + strlen(Cmdstr)))
  611.         {
  612.             Exitcode = 0200;
  613.             canit();
  614.         }
  615.     } else if (wcsend(npats, patts) == ERROR)
  616.     {
  617.         Exitcode = 0200;
  618.         canit();
  619.     }
  620.     if ( endmsg[0] )
  621.     {
  622. #ifdef    DEBUG
  623.         USR_printf("\n%s\n", endmsg);
  624. #endif
  625.         RS_printf(RsPort,"\r\n%s", endmsg);
  626.     }
  627.  
  628. #ifdef    __TOWNS__
  629.     USR_fprintf(stderr,"\nrx ver.%s finished.\n",MAIN_VER);
  630. #else
  631.     RS_printf(RsPort,"\r\n%s %s finished.\r\n", Progname, VERSION);
  632. #endif
  633.     mode(0);    /* restore original tty mode */
  634.     dm = ((errcnt != 0) | Exitcode);
  635.     if (dm)
  636.         cucheck();
  637.     EXIT(dm);
  638.     /* NOTREACHED */
  639. }
  640.  
  641. static    int        wcsend(int argc, char *argp[])
  642. {
  643.     register    n;
  644.  
  645.     Crcflg = FALSE;
  646.     firstsec = TRUE;
  647.     bytcnt = -1;
  648.     if (Nozmodem)
  649.     {
  650.         RS_puts(RsPort,"Start your YMODEM receive. ");
  651.     }
  652.     for (n = 0; n < argc; ++n)
  653.     {
  654.         Totsecs = 0;
  655.         if (wcs(argp[n]) == ERROR)
  656.             return ERROR;
  657.     }
  658.     Totsecs = 0;
  659.     if (Filcnt == 0)
  660.     {                            /* bitch if we couldn't open ANY files */
  661.         if (!Nozmodem && !Modem2)
  662.         {
  663.             Command = TRUE;
  664.             Cmdstr = "echo \"sz: Can't open any requested files\"";
  665.             if (getnak())
  666.             {
  667.                 Exitcode = 0200;
  668.                 canit();
  669.             }
  670.             if (!Zmodem)
  671.                 canit();
  672.             else if (zsendcmd(Cmdstr, 1 + strlen(Cmdstr)))
  673.             {
  674.                 Exitcode = 0200;
  675.                 canit();
  676.             }
  677.             Exitcode = 1;
  678.             return OK;
  679.         }
  680.         canit();
  681.         sprintf(endmsg, "Can't open any requested files");
  682.         return ERROR;
  683.     }
  684.     if (Zmodem)
  685.         saybibi();
  686.     else if (!Modem2)
  687.         wctxpn("");
  688.     return OK;
  689. }
  690.  
  691. static    int        wcs(char *oname)
  692. {
  693. //    register char *p, *q;
  694.     struct stat f;
  695.     char        name[PATHLEN];
  696.  
  697.     strcpy(name, oname);
  698.  
  699.     if (Restricted)
  700.     {
  701.         /* restrict pathnames to current tree or uucppublic */
  702.         if (substr(name, "../")
  703.             || (name[0] == '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) )
  704.         {
  705.             canit();
  706.             sprintf(endmsg, "Security Violation");
  707.             return ERROR;
  708.         }
  709.     }
  710.     infile = oname;    in = FM_fopen(oname, ROPMODE);
  711.  
  712.     if (in == NULL)
  713.     {
  714.         ++errcnt;
  715.         return OK;                /* pass over it, there may be others */
  716.     }
  717.     BEofseen = Eofseen = 0;
  718.     vpos = 0;
  719.  
  720.     /* Check for directory or block special files */
  721. #ifdef    _FSTAT_IGN
  722.     stat(infile, &f);
  723. #else
  724.     fstat(fileno(in), &f);
  725. #endif
  726. #ifndef    __TOWNS__
  727.     {
  728.         register    c;
  729.  
  730.         c = f.st_mode & S_IFMT;
  731.         if (c == S_IFDIR || c == S_IFBLK)
  732.         {
  733.             FM_fclose(in);
  734.             return OK;
  735.         }
  736.     }
  737. #endif
  738.     ++Filcnt;
  739.     switch (wctxpn(name))
  740.     {
  741.         case ERROR:
  742.             return ERROR;
  743.         case ZSKIP:
  744.             return OK;
  745.     }
  746.     if (!Zmodem && wctx(f.st_size) == ERROR)
  747.         return ERROR;
  748.  
  749.     if (Unlinkafter)
  750.         unlink(oname);
  751.  
  752.     return 0;
  753. }
  754.  
  755. /*
  756.  * generate and transmit pathname block consisting of pathname (null
  757.  * terminated), file length, mode time and file mode in octal as provided by
  758.  * the Unix fstat call. N.B.: modifies the passed name, may extend it!
  759.  */
  760. static    int        wctxpn(char *name)
  761. {
  762.     register char *p, *q;
  763.     char        name2[PATHLEN];
  764.     struct stat f;
  765.  
  766. #ifdef    __TOWNS__
  767.     char    tmp[PATHLEN];
  768.     FS_dos2unix( tmp, name );
  769.     if ( !Fullname && isalpha(tmp[0]) && tmp[1] == ':' )
  770.         name = &tmp[2];
  771.     else
  772.         name = tmp;
  773. #endif
  774.  
  775.     if (Modem2)
  776.     {
  777. #ifdef    _FSTAT_IGN
  778.         if (*name && stat(infile, &f) != -1)
  779. #else
  780.         if (*name && fstat(fileno(in), &f) != -1)
  781. #endif
  782.         {
  783.             USR_fprintf(stderr, "Sending %s, %ld XMODEM blocks. ",
  784.                     name, (127 + f.st_size) >> 7);
  785.         }
  786.         USR_fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
  787.         return OK;
  788.     }
  789.     zperr("Awaiting pathname nak for %s", *name ? name : "<END>");
  790.     if (!Zmodem)
  791.     {
  792.         if (getnak())
  793.             return ERROR;
  794.     }
  795.  
  796.     q = (char *) 0;
  797.     if (Dottoslash)
  798.     {                            /* change . to . */
  799.         for (p = name; *p; ++p)
  800.         {
  801.             if (*p == '/')
  802.                 q = p;
  803.             else if (*p == '.')
  804.                 *(q = p) = '/';
  805.         }
  806.         if (q && strlen(++q) > 8)
  807.         {                        /* If name>8 chars */
  808.             q += 8;             /* make it .ext */
  809.             strcpy(name2, q);    /* save excess of name */
  810.             *q = '.';
  811.             strcpy(++q, name2); /* add it back */
  812.         }
  813.     }
  814.     for (p = name, q = txbuf; *p;)
  815.     {
  816.         if ((*q++ = *p++) == '/' && !Fullname)
  817.             q = txbuf;
  818.     }
  819.     *q++ = 0;
  820.     p = q;
  821.     while (q < (txbuf + 1024))
  822.         *q++ = 0;
  823.     if (*name)
  824.     {
  825. #ifdef    _FSTAT_IGN
  826.         if ( stat(infile, &f) != -1 )
  827. #else
  828.         if ( fstat(fileno(in), &f) != -1 )
  829. #endif
  830.             sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime,
  831.                     f.st_mode, Filesleft, Totalleft);
  832.         USR_fprintf(stderr,"\nSend header : %s\n", p );
  833.         Totalleft -= f.st_size;
  834.     }
  835.     if (--Filesleft <= 0)
  836.         Totalleft = 0;
  837.     if (Totalleft < 0)
  838.         Totalleft = 0;
  839.  
  840.     /* force 1k blocks if name won't fit in 128 byte block */
  841.     if (txbuf[125])
  842.         blklen = 1024;
  843.     else
  844.     {                            /* A little goodie for IMP/KMD */
  845.         txbuf[127] = (f.st_size + 127) >> 7;
  846.         txbuf[126] = (f.st_size + 127) >> 15;
  847.     }
  848.     if (Zmodem)
  849.         return zsendfile(txbuf, 1 + strlen(p) + (p - txbuf));
  850.     if (wcputsec(txbuf, 0, 128) == ERROR)
  851.         return ERROR;
  852.     return OK;
  853. }
  854.  
  855. static    int        getnak(void)
  856. {
  857.     register    firstch;
  858.  
  859.     Lastrx = 0;
  860.     for (;;)
  861.     {
  862.         switch (firstch = readline(800))
  863.         {
  864.             case ZPAD:
  865.                 if (getzrxinit())
  866.                     return ERROR;
  867.                 Ascii = 0;        /* Receiver does the conversion */
  868.                 return FALSE;
  869.             case TIMEOUT:
  870.                 sprintf(endmsg, "Timeout waiting for ZRINIT");
  871.                 return TRUE;
  872.             case WANTG:
  873. #ifdef MODE2OK
  874.                 mode(2);        /* Set cbreak, XON/XOFF, etc. */
  875.                 /* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
  876. #endif
  877.                 Optiong = TRUE;
  878.                 blklen = 1024;
  879.             case WANTCRC:
  880.                 Crcflg = TRUE;
  881.             case NAK:
  882.                 return FALSE;
  883.             case CAN:
  884.                 if ((firstch = readline(20)) == CAN && Lastrx == CAN)
  885.                 {
  886.                     sprintf(endmsg, "Got CAN waiting to send file");
  887.                     return TRUE;
  888.                 }
  889.             default:
  890.                 break;
  891.         }
  892.         Lastrx = firstch;
  893.     }
  894. }
  895.  
  896.  
  897. static    int        wctx(long flen)
  898. {
  899.     register int thisblklen;
  900.     register int sectnum, attempts, firstch;
  901.     long        charssent;
  902.  
  903.     charssent = 0;
  904.     firstsec = TRUE;
  905.     thisblklen = blklen;
  906.     vfile("wctx:file length=%ld", flen);
  907.  
  908.     while ((firstch = readline(Rxtimeout)) != NAK && firstch != WANTCRC
  909.            && firstch != WANTG && firstch != TIMEOUT && firstch != CAN)
  910.         ;
  911.     if (firstch == CAN)
  912.     {
  913.         zperr("Receiver CANcelled");
  914.         return ERROR;
  915.     }
  916.     if (firstch == WANTCRC)
  917.         Crcflg = TRUE;
  918.     if (firstch == WANTG)
  919.         Crcflg = TRUE;
  920.     sectnum = 0;
  921.     for (;;)
  922.     {
  923.         if (flen <= (charssent + 896L))
  924.             thisblklen = 128;
  925.         if (!filbuf(txbuf, thisblklen))
  926.             break;
  927.         if (wcputsec(txbuf, ++sectnum, thisblklen) == ERROR)
  928.             return ERROR;
  929.         charssent += thisblklen;
  930.     }
  931.     FM_fclose(in);
  932.     attempts = 0;
  933.     do
  934.     {
  935.         purgeline();
  936.         sendline(EOT);
  937.         flushmo();
  938.         ++attempts;
  939.     }
  940.     while ( ((firstch = (readline(Rxtimeout))) != ACK) && attempts < RETRYMAX);
  941.     if (attempts == RETRYMAX)
  942.     {
  943.         zperr("No ACK on EOT");
  944.         return ERROR;
  945.     } else
  946.         return OK;
  947. }
  948.  
  949. /* data length of this sector to send */
  950. static    int        wcputsec(char *buf, int sectnum, int cseclen)
  951. {
  952.     register    checksum, wcj;
  953.     register char *cp;
  954.     unsigned    oldcrc;
  955.     int         firstch;
  956.     int         attempts;
  957.  
  958.     firstch = 0;                /* part of logic to detect CAN CAN */
  959.  
  960.     if (Verbose > 2)
  961.         USR_fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs / 8);
  962.     else if (Verbose > 1)
  963.         USR_fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs / 8);
  964.     for (attempts = 0; attempts <= RETRYMAX; attempts++)
  965.     {
  966.         Lastrx = firstch;
  967.         sendline(cseclen == 1024 ? STX : SOH);
  968.         sendline(sectnum);
  969.         sendline(-sectnum - 1);
  970.         oldcrc = checksum = 0;
  971.         for (wcj = cseclen, cp = buf; --wcj >= 0;)
  972.         {
  973.             sendline(*cp);
  974.             oldcrc = updcrc((0377 & *cp), oldcrc);
  975.             checksum += *cp++;
  976.         }
  977.         if (Crcflg)
  978.         {
  979.             oldcrc = updcrc(0, updcrc(0, oldcrc));
  980.             sendline((int) oldcrc >> 8);
  981.             sendline((int) oldcrc);
  982.         } else
  983.             sendline(checksum);
  984.         flushmo();
  985.  
  986.         if (Optiong)
  987.         {
  988.             firstsec = FALSE;
  989.             return OK;
  990.         }
  991.         firstch = readline(Rxtimeout);
  992.       gotnak:
  993.         switch (firstch)
  994.         {
  995.             case CAN:
  996.                 if (Lastrx == CAN)
  997.                 {
  998.                   cancan:
  999.                     zperr("Cancelled");
  1000.                     return ERROR;
  1001.                 }
  1002.                 break;
  1003.             case TIMEOUT:
  1004.                 zperr("Timeout on sector ACK");
  1005.                 continue;
  1006.             case WANTCRC:
  1007.                 if (firstsec)
  1008.                     Crcflg = TRUE;
  1009.             case NAK:
  1010.                 zperr("NAK on sector");
  1011.                 continue;
  1012.             case ACK:
  1013.                 firstsec = FALSE;
  1014.                 Totsecs += (cseclen >> 7);
  1015.                 return OK;
  1016.             case ERROR:
  1017.                 zperr("Got burst for sector ACK");
  1018.                 break;
  1019.             default:
  1020.                 zperr("Got %02x for sector ACK", firstch);
  1021.                 break;
  1022.         }
  1023.         for (;;)
  1024.         {
  1025.             Lastrx = firstch;
  1026.             if ((firstch = readline(Rxtimeout)) == TIMEOUT)
  1027.                 break;
  1028.             if (firstch == NAK || firstch == WANTCRC)
  1029.                 goto gotnak;
  1030.             if (firstch == CAN && Lastrx == CAN)
  1031.                 goto cancan;
  1032.         }
  1033.     }
  1034.     zperr("Retry Count Exceeded");
  1035.     return ERROR;
  1036. }
  1037.  
  1038. /* fill buf with count chars padding with ^Z for CPM */
  1039. static    int        filbuf(register char *buf, int count)
  1040. {
  1041.     register    c, m;
  1042.  
  1043.     if (!Ascii)
  1044.     {
  1045. #ifndef    __TOWNS__
  1046.         m = read(fileno(in), buf, count);
  1047. #else
  1048.         m = fread(buf,1,count,in);
  1049. #endif
  1050.         if (m <= 0)
  1051.             return 0;
  1052.         while (m < count)
  1053.             buf[m++] = 032;
  1054.         return count;
  1055.     }
  1056.     m = count;
  1057.     if (Lfseen)
  1058.     {
  1059.         *buf++ = 012;
  1060.         --m;
  1061.         Lfseen = 0;
  1062.     }
  1063.     while ((c = getc(in)) != EOF)
  1064.     {
  1065.         if (c == 012)
  1066.         {
  1067.             *buf++ = 015;
  1068.             if (--m == 0)
  1069.             {
  1070.                 Lfseen = TRUE;
  1071.                 break;
  1072.             }
  1073.         }
  1074.         *buf++ = c;
  1075.         if (--m == 0)
  1076.             break;
  1077.     }
  1078.     if (m == count)
  1079.         return 0;
  1080.     else
  1081.         while (--m >= 0)
  1082.             *buf++ = CPMEOF;
  1083.     return count;
  1084. }
  1085.  
  1086. /* Fill buffer with blklen chars */
  1087. static    int        zfilbuf(void)
  1088. {
  1089.     int         n;
  1090.  
  1091. #ifdef TXBSIZE
  1092.     vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, blklen);
  1093.     /* We assume request is within buffer, or just beyond */
  1094.     txbuf = Txb + (bytcnt & TXBMASK);
  1095.     if (vpos <= bytcnt)
  1096.     {
  1097.         n = fread(txbuf, 1, blklen, in);
  1098.  
  1099.         vpos += n;
  1100.         if (n < blklen)
  1101.             Eofseen = 1;
  1102.         vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen);
  1103.         return n;
  1104.     }
  1105.     if (vpos >= (bytcnt + blklen))
  1106.         return blklen;
  1107.     /* May be a short block if crash recovery etc. */
  1108.     Eofseen = BEofseen;
  1109.     return (vpos - bytcnt);
  1110. #else
  1111.     n = fread(txbuf, 1, blklen, in);
  1112.     if (n < blklen)
  1113.         Eofseen = 1;
  1114.     return n;
  1115. #endif
  1116. }
  1117.  
  1118. #ifdef TXBSIZE
  1119. /* Replacement for brain damaged fseek function.  Returns 0==success */
  1120. static    int        fooseek(FILE * fptr, long pos, int whence)
  1121. {
  1122.     long        m, n;
  1123.  
  1124.     vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
  1125.     /* Seek offset < current buffer */
  1126.     if (pos < (vpos - TXBSIZE + 1024))
  1127.     {
  1128.         BEofseen = 0;
  1129.         if (Canseek > 0)
  1130.         {
  1131.             vpos = pos & ~TXBMASK;
  1132.             if (vpos >= pos)
  1133.                 vpos -= TXBSIZE;
  1134.             if (fseek(fptr, vpos, 0))
  1135.                 return 1;
  1136.         } else if (Canseek == 0)
  1137.         {
  1138.             if (fseek(fptr, vpos = 0L, 0))
  1139.                 return 1;
  1140.         } else
  1141.             return 1;
  1142.         while (vpos < pos)
  1143.         {
  1144.             n = fread(Txb, 1, TXBSIZE, fptr);
  1145.             vpos += n;
  1146.             vfile("n=%d vpos=%ld", n, vpos);
  1147.             if (n < TXBSIZE)
  1148.             {
  1149.                 BEofseen = 1;
  1150.                 break;
  1151.             }
  1152.         }
  1153.         vfile("vpos=%ld", vpos);
  1154.         return 0;
  1155.     }
  1156.     /* Seek offset > current buffer (Crash Recovery, etc.) */
  1157.     if (pos > vpos)
  1158.     {
  1159.         if (Canseek)
  1160.             if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
  1161.                 return 1;
  1162.         while (vpos <= pos)
  1163.         {
  1164.             txbuf = Txb + (vpos & TXBMASK);
  1165.             m = TXBSIZE - (vpos & TXBMASK);
  1166.             vfile("m=%ld vpos=%ld", m, vpos);
  1167.             n = fread(txbuf, 1, m, fptr);
  1168.             vfile("n=%ld vpos=%ld", n, vpos);
  1169.             vpos += n;
  1170.             vfile("bo=%d m=%ld vpos=%ld", txbuf - Txb, m, vpos);
  1171.             if (n < m)
  1172.             {
  1173.                 BEofseen = 1;
  1174.                 break;
  1175.             }
  1176.         }
  1177.         return 0;
  1178.     }
  1179.     /* Seek offset is within current buffer */
  1180.     vfile("within buffer: vpos=%ld", vpos);
  1181.     return 0;
  1182. }
  1183. #define fseek fooseek
  1184. #endif
  1185.  
  1186.  
  1187. /* VARARGS1 */
  1188. static    void    vfile( CONST char *form, ... )
  1189. {
  1190.     va_list        arg;
  1191.     char        tmp[BUFSIZ];
  1192.  
  1193.     if ( Verbose > 2 )
  1194.     {
  1195.         va_start( arg, form );
  1196.         vsprintf( tmp, form, arg );
  1197.         va_end(arg);
  1198.         USR_fputs(tmp, stderr );
  1199.         USR_fputs("\n",stderr);
  1200.     }
  1201. }
  1202.  
  1203. #ifndef    __TOWNS__
  1204. static    void    alrm(void)
  1205. {
  1206.     longjmp(tohere, -1);
  1207. }
  1208. #endif
  1209.  
  1210.  
  1211. /*
  1212.  * readline(timeout) reads character(s) from file descriptor 0 timeout is in
  1213.  * tenths of seconds
  1214.  */
  1215. static    int        readline(int timeout)
  1216. {
  1217.     register int c;
  1218.     static char byt[1];
  1219.  
  1220.     if (setjmp(tohere))
  1221.     {
  1222.         zperr("TIMEOUT");
  1223.         return TIMEOUT;
  1224.     }
  1225. #ifdef    __TOWNS__
  1226.     c = timeout;
  1227.     if (c < 200 )
  1228.         c = 200;
  1229.     if (Verbose > 5)
  1230.     {
  1231.         USR_fprintf(stderr, "Timeout=%4d Calling alarm(%4d) ", timeout, c);
  1232.     }
  1233.     {
  1234.         clock_t    clk;
  1235.         clk = H_CLOCK2(0) + c * CLOCKS_PER_SEC / 100;
  1236.         do
  1237.         {    if ( (c = RS_chk(RsPort)) > 0 )
  1238.             {
  1239.                 byt[0] = RS_getc(RsPort);
  1240.                 break;
  1241.             }
  1242.         } while ( clk > H_CLOCK2(clk) );
  1243.     }
  1244. #else
  1245.     c = timeout / 10;
  1246.     if (c < 2)
  1247.         c = 2;
  1248.     if (Verbose > 5)
  1249.     {
  1250.         USR_fprintf(stderr, "Timeout=%5d Calling alarm(%d) ", timeout, c);
  1251.     }
  1252.     signal(SIGALRM, alrm);
  1253.     alarm(c);
  1254.     c = read(0, byt, 1);
  1255.     alarm(0);
  1256. #endif
  1257.     if (Verbose > 5)
  1258.     {
  1259.         if (c < 1)
  1260.             USR_fprintf(stderr, "timeout!!\n" );
  1261.         else
  1262.             USR_fprintf(stderr, "ret %02X\n", byt[0] & 0377);
  1263.     }
  1264.     if (c < 1)
  1265.         return TIMEOUT;
  1266.     return (byt[0] & 0377);
  1267. }
  1268.  
  1269. static    void    flushmo(void)
  1270. {
  1271. }
  1272.  
  1273.  
  1274. static    void    purgeline(void)
  1275. {
  1276. #ifndef    __TOWNS__
  1277. #ifdef USG
  1278.     ioctl(0, TCFLSH, 0);
  1279. #else
  1280.     lseek(0, 0L, 2);
  1281. #endif
  1282. #endif
  1283. }
  1284.  
  1285. /* send cancel string to get the other end to shut up */
  1286. static    void    canit(void)
  1287. {
  1288.     static char canistr[] =
  1289.     {
  1290.      24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0
  1291.     };
  1292.  
  1293.     RS_puts(RsPort,canistr);
  1294. }
  1295.  
  1296. /* Log an error */
  1297. /* VARARGS1 */
  1298. #ifdef    __HIGHC__
  1299. static    void    zperr(char *form, ... )
  1300. {
  1301.     va_list        arg;
  1302.     char        tmp[BUFSIZ];
  1303.  
  1304.     if (Verbose <= 0)
  1305.         return;
  1306.     USR_fprintf(stderr, "Retry %d: ", errors);
  1307.     va_start( arg, form );
  1308.     vsprintf( tmp, form, arg );
  1309.     va_end(arg);
  1310.     USR_fputs(tmp, stderr );
  1311.     USR_fputs("\n",stderr);
  1312. }
  1313. #else
  1314. static    void    zperr(char *s, char *p, char *u)
  1315. {
  1316.     if (Verbose <= 0)
  1317.         return;
  1318.     USR_fprintf(stderr, "Retry %d: ", errors);
  1319.     USR_fprintf(stderr, s, p, u);
  1320.     USR_fprintf(stderr, "\n");
  1321. }
  1322. #endif
  1323.  
  1324. /*
  1325.  * substr(string, token) searches for token in string s returns pointer to
  1326.  * token within string if found, NULL otherwise
  1327.  */
  1328. static    char    *substr(register char *s, register char *t)
  1329. {
  1330.     register char *ss, *tt;
  1331.     /* search for first char of token */
  1332.     for (ss = s; *s; s++)
  1333.         if (*s == *t)
  1334.             /* compare token with substring */
  1335.             for (ss = s, tt = t;;)
  1336.             {
  1337.                 if (*tt == 0)
  1338.                     return s;
  1339.                 if (*ss++ != *tt++)
  1340.                     break;
  1341.             }
  1342.     return NULL;
  1343. }
  1344.  
  1345. #include    "szhelp.c"
  1346.  
  1347. /* Send send-init information */
  1348. static    int        getzrxinit(void)
  1349. {
  1350.     register    n;
  1351.     struct stat f;
  1352.  
  1353.     for (n = 10; --n >= 0;)
  1354.     {
  1355.  
  1356.         switch (zgethdr(Rxhdr, 1))
  1357.         {
  1358.             case ZCHALLENGE:    /* Echo receiver's challenge numbr */
  1359.                 stohdr(Rxpos);
  1360.                 zshhdr(4, ZACK, Txhdr);
  1361.                 continue;
  1362.             case ZCOMMAND:        /* They didn't see out ZRQINIT */
  1363.                 stohdr(0L);
  1364.                 zshhdr(4, ZRQINIT, Txhdr);
  1365.                 continue;
  1366.             case ZRINIT:
  1367.                 Rxflags = 0377 & Rxhdr[ZF0];
  1368.                 Usevhdrs = Rxhdr[ZF1] & CANVHDR;
  1369.                 Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
  1370.                 Zctlesc |= Rxflags & TESCCTL;
  1371.                 Rxbuflen = (0377 & Rxhdr[ZP0]) + ((0377 & Rxhdr[ZP1]) << 8);
  1372.                 if (!(Rxflags & CANFDX))
  1373.                     Txwindow = 0;
  1374.                 vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
  1375. #ifndef    __TOWNS__
  1376.                 if (!Fromcu)
  1377.                     signal(SIGINT, SIG_IGN);
  1378. #else
  1379.                 if (!Fromcu)
  1380.                 {
  1381.                     SIGNAL(SIGINT, SIG_IGN);
  1382.                     CtrlX = FALSE;
  1383.                 }
  1384. #endif
  1385. #ifdef MODE2OK
  1386.                 mode(2);        /* Set cbreak, XON/XOFF, etc. */
  1387.                 /* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
  1388. #endif
  1389.  
  1390. #ifndef READCHECK
  1391. #ifndef USG
  1392.                 /* Use 1024 byte frames if no sample/interrupt */
  1393.                 if (Rxbuflen < 32 || Rxbuflen > 1024)
  1394.                 {
  1395.                     Rxbuflen = 1024;
  1396.                     vfile("Rxbuflen=%d", Rxbuflen);
  1397.                 }
  1398. #endif
  1399. #endif
  1400.  
  1401.                 /* Override to force shorter frame length */
  1402.                 if (Rxbuflen && (Rxbuflen > Tframlen) && (Tframlen >= 32))
  1403.                     Rxbuflen = Tframlen;
  1404.                 if (!Rxbuflen && (Tframlen >= 32) && (Tframlen <= 1024))
  1405.                     Rxbuflen = Tframlen;
  1406.                 vfile("Rxbuflen=%d", Rxbuflen);
  1407.  
  1408.                 /* If using a pipe for testing set lower buf len */
  1409. #ifdef    __TOWNS__
  1410.             //    Rxbuflen = 1024;
  1411. #else
  1412.                 fstat(0, &f);
  1413.                 if ((f.st_mode & S_IFMT) != S_IFCHR)
  1414.                 {
  1415.                     Rxbuflen = 1024;
  1416.                 }
  1417. #endif
  1418.                 /*
  1419.                  * If input is not a regular file, force ACK's to prevent
  1420.                  * running beyond the buffer limits
  1421.                  */
  1422.                 if (!Command)
  1423.                 {
  1424. #ifdef    _FSTAT_IGN
  1425.                     stat(infile, &f);
  1426. #else
  1427.                     fstat(fileno(in), &f);
  1428. #endif
  1429.                     if ((f.st_mode & S_IFMT) != S_IFREG)
  1430.                     {
  1431.                         Canseek = -1;
  1432. #ifdef TXBSIZE
  1433.                         Txwindow = TXBSIZE - 1024;
  1434.                         Txwspac = TXBSIZE / 4;
  1435. #else
  1436.                         return ERROR;
  1437. #endif
  1438.                     }
  1439.                 }
  1440.                 /* Set initial subpacket length */
  1441.                 if (blklen < 1024)
  1442.                 {                /* Command line override? */
  1443.                     if (Effbaud > 300)
  1444.                         blklen = 256;
  1445.                     if (Effbaud > 1200)
  1446.                         blklen = 512;
  1447.                     if (Effbaud > 2400)
  1448.                         blklen = 1024;
  1449.                 }
  1450.                 if (Rxbuflen && blklen > Rxbuflen)
  1451.                     blklen = Rxbuflen;
  1452.                 if (blkopt && blklen > blkopt)
  1453.                     blklen = blkopt;
  1454.                 vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
  1455.                 vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
  1456.  
  1457.  
  1458.                 if (Lztrans == ZTRLE && (Rxflags & CANRLE))
  1459.                     Txfcs32 = 2;
  1460.                 else
  1461.                     Lztrans = 0;
  1462.  
  1463.                 return (sendzsinit());
  1464.             case ZCAN:
  1465.             case TIMEOUT:
  1466.                 return ERROR;
  1467.             case ZRQINIT:
  1468.                 if (Rxhdr[ZF0] == ZCOMMAND)
  1469.                     continue;
  1470.             default:
  1471.                 zshhdr(4, ZNAK, Txhdr);
  1472.                 continue;
  1473.         }
  1474.     }
  1475.     return ERROR;
  1476. }
  1477.  
  1478. /* Send send-init information */
  1479. static    int        sendzsinit(void)
  1480. {
  1481.     register    c;
  1482.  
  1483.     if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
  1484.         return OK;
  1485.     errors = 0;
  1486.     for (;;)
  1487.     {
  1488.         stohdr(0L);
  1489. #ifdef ALTCANOFF
  1490.         Txhdr[ALTCOFF] = ALTCANOFF;
  1491. #endif
  1492.         if (Zctlesc)
  1493.         {
  1494.             Txhdr[ZF0] |= TESCCTL;
  1495.             zshhdr(4, ZSINIT, Txhdr);
  1496.         } else
  1497.             zsbhdr(4, ZSINIT, Txhdr);
  1498.         zsdata(Myattn, ZATTNLEN, ZCRCW);
  1499.         c = zgethdr(Rxhdr, 1);
  1500.         switch (c)
  1501.         {
  1502.             case ZCAN:
  1503.                 return ERROR;
  1504.             case ZACK:
  1505.                 return OK;
  1506.             default:
  1507.                 if (++errors > 19)
  1508.                     return ERROR;
  1509.                 continue;
  1510.         }
  1511.     }
  1512. }
  1513.  
  1514. /* Send file name and related info */
  1515. static    int        zsendfile(char *buf, int blen)
  1516. {
  1517.     register    c;
  1518.     register UNSL long crc;
  1519.     long        lastcrcrq = -1;
  1520. //    char       *p;
  1521.  
  1522. #ifdef    DEBUG
  1523.     USR_fprintf(stderr,"zsendfile(buf,buflen = %d)\n", blen);
  1524. #endif
  1525.     for (errors = 0; ++errors < 11;)
  1526.     {
  1527.         Txhdr[ZF0] = Lzconv;    /* file conversion request */
  1528.         Txhdr[ZF1] = Lzmanag;    /* file management request */
  1529.         if (Lskipnocor)
  1530.             Txhdr[ZF1] |= ZMSKNOLOC;
  1531.         Txhdr[ZF2] = Lztrans;    /* file transport request */
  1532.         Txhdr[ZF3] = 0;
  1533.         zsbhdr(4, ZFILE, Txhdr);
  1534.         zsdata(buf, blen, ZCRCW);
  1535.       again:
  1536.         c = zgethdr(Rxhdr, 1);
  1537.         switch (c)
  1538.         {
  1539.             case ZRINIT:
  1540.                 while ((c = readline(50)) > 0)
  1541.                 {
  1542.                     if ( c == ZPAD )
  1543.                         goto again;
  1544.                 }
  1545.                 continue;
  1546.             case ZCAN:
  1547.             case TIMEOUT:
  1548.             case ZABORT:
  1549.             case ZFIN:
  1550.                 sprintf(endmsg, "Got %s on pathname", frametypes[c + FTOFFSET]);
  1551.                 return ERROR;
  1552.             default:
  1553.                 sprintf(endmsg, "Got %d frame type on pathname", c);
  1554.                 return ERROR;
  1555.             case ERROR:
  1556.             case ZNAK:
  1557.                 continue;
  1558.             case ZCRC:
  1559.                 if (Rxpos != lastcrcrq)
  1560.                 {
  1561.                     lastcrcrq = Rxpos;
  1562.                     crc = 0xFFFFFFFFL;
  1563.                     if (Canseek >= 0)
  1564.                     {
  1565.                         fseek(in, 0L, 0);
  1566.                         while ( ((c = fgetc(in)) != EOF) && --lastcrcrq )
  1567.                             crc = UPDC32(c, crc);
  1568.                         crc = ~crc;
  1569.                         clearerr(in);    /* Clear possible EOF */
  1570.                         lastcrcrq = Rxpos;
  1571.                     }
  1572.                 }
  1573.                 stohdr(crc);
  1574.                 zsbhdr(4, ZCRC, Txhdr);
  1575.                 goto again;
  1576.             case ZFERR:
  1577.             case ZSKIP:
  1578.                 sprintf(endmsg, "File skipped by receiver request");
  1579.                 FM_fclose(in);
  1580.                 return c;
  1581.             case ZRPOS:
  1582.                 /*
  1583.                  * Suppress zcrcw request otherwise triggered by
  1584.                  * lastyunc==bytcnt
  1585.                  */
  1586.                 if (fseek(in, Rxpos, 0))
  1587.                     return ERROR;
  1588.                 Lastsync = (long)(bytcnt = Txpos = Lrxpos = Rxpos) - 1l;
  1589.                 return zsendfdata();
  1590.         }
  1591.     }
  1592. }
  1593.  
  1594. /* Send the data in the file */
  1595. static    int        zsendfdata(void)
  1596. {
  1597.     register    c, e, n;
  1598.     register    newcnt;
  1599.     register long tcount = 0;
  1600.     int         junkcount;        /* Counts garbage chars received by TX */
  1601.     static int    tleft = 6;        /* Counter for test mode */
  1602.  
  1603. #ifdef    DEBUG
  1604.     USR_fprintf(stderr,"zsenfdata \n");
  1605. #endif
  1606.     junkcount = 0;
  1607.     Beenhereb4 = FALSE;
  1608. somemore:
  1609.     if ( setjmp(intrjmp) )
  1610.     {
  1611.       waitack:
  1612.         junkcount = 0;
  1613.         c = getinsync(0);
  1614.       gotack:
  1615.         switch (c)
  1616.         {
  1617.             default:
  1618.             case ZCAN:
  1619.                 FM_fclose(in);
  1620.                 return ERROR;
  1621.             case ZSKIP:
  1622.                 FM_fclose(in);
  1623.                 return c;
  1624.             case ZACK:
  1625.             case ZRPOS:
  1626.                 break;
  1627.             case ZRINIT:
  1628.                 FM_fclose(in);    in = NULL;
  1629.                 return OK;
  1630.         }
  1631. #ifdef READCHECK
  1632.         /*
  1633.          * If the reverse channel can be tested for data, this logic may be
  1634.          * used to detect error packets sent by the receiver, in place of
  1635.          * setjmp/longjmp rdchk(fd) returns non 0 if a character is available
  1636.          */
  1637.         while (rdchk(0))
  1638.         {
  1639. #ifdef EATSIT
  1640.             switch (checked)
  1641. #else
  1642.             switch (readline(1))
  1643. #endif
  1644.             {
  1645.                 case CAN:
  1646.                 case ZPAD:
  1647.                     c = getinsync(1);
  1648.                     goto gotack;
  1649.                 case XOFF:        /* Wait a while for an XON */
  1650.                 case XOFF | 0200:
  1651.                     readline(100);
  1652.             }
  1653.         }
  1654. #endif
  1655.     }
  1656. #ifndef    __TOWNS__
  1657.     if (!Fromcu)
  1658.         signal(SIGINT, onintr);
  1659. #else
  1660.     if (!Fromcu)
  1661.     {
  1662.         CtrlX = TRUE;
  1663.         SIGNAL(SIGINT, onintr);
  1664.     }
  1665. #endif
  1666.     newcnt = Rxbuflen;
  1667.     Txwcnt = 0;
  1668.     stohdr(Txpos);
  1669.     zsbhdr(4, ZDATA, Txhdr);
  1670.  
  1671.     /*
  1672.      * Special testing mode.  This should force receiver to Attn,ZRPOS many
  1673.      * times.  Each time the signal should be caught, causing the file to be
  1674.      * started over from the beginning.
  1675.      */
  1676.     if (Test)
  1677.     {
  1678.         if (--tleft)
  1679.             while (tcount < 20000)
  1680.             {
  1681.                 RS_puts(RsPort,qbf);
  1682.                 tcount += strlen(qbf);
  1683. #ifdef READCHECK
  1684.                 while (rdchk(0))
  1685.                 {
  1686. #ifdef EATSIT
  1687.                     switch (checked)
  1688. #else
  1689.                     switch (readline(1))
  1690. #endif
  1691.                     {
  1692.                         case CAN:
  1693.                         case ZPAD:
  1694. #ifndef    __TOWNS__
  1695. #    ifdef TCFLSH
  1696.                             ioctl(0, TCFLSH, 1);
  1697. #    endif
  1698. #endif
  1699.                             goto waitack;
  1700.                         case XOFF:        /* Wait for XON */
  1701.                         case XOFF | 0200:
  1702.                             readline(100);
  1703.                     }
  1704.                 }
  1705. #endif
  1706.             }
  1707. #ifndef    __TOWNS__
  1708.         signal(SIGINT, SIG_IGN);
  1709. #else
  1710.         SIGNAL(SIGINT, SIG_IGN);
  1711.         CtrlX = FALSE;
  1712. #endif
  1713.         canit();
  1714. #ifdef    __TOWNS__
  1715.         {
  1716.             clock_t    clk;
  1717.             clk = H_CLOCK2(0) + 3 * CLOCKS_PER_SEC;
  1718.             while ( clk > H_CLOCK2(clk) )
  1719.                 ;
  1720.         }
  1721. #else
  1722.         sleep(3);
  1723. #endif
  1724.         purgeline();
  1725.         mode(0);    /* restore original tty mode */
  1726.         USR_printf("\nsz: Tcount = %ld\n", tcount);
  1727.         if (tleft)
  1728.         {
  1729.             USR_printf("ERROR: Interrupts Not Caught\n");
  1730.             EXIT(1);
  1731.         }
  1732.         EXIT(0);
  1733.     }
  1734.     do
  1735.     {
  1736.         n = zfilbuf();
  1737.         if (Eofseen)
  1738.             e = ZCRCE;
  1739.         else if (junkcount > 3)
  1740.             e = ZCRCW;
  1741.         else if (bytcnt == Lastsync)
  1742.             e = ZCRCW;
  1743.         else if (Rxbuflen && (newcnt -= n) <= 0)
  1744.             e = ZCRCW;
  1745.         else if (Txwindow && (Txwcnt += n) >= Txwspac)
  1746.         {
  1747.             Txwcnt = 0;
  1748.             e = ZCRCQ;
  1749.         } else
  1750.             e = ZCRCG;
  1751.         if (Verbose > 1)
  1752.         {
  1753.             USR_fprintf(stderr, "\r%7ld ZMODEM%s    ",
  1754.                     Txpos, Crc32t ? " CRC-32" : "");
  1755.         }
  1756.         zsdata(txbuf, n, e);
  1757.         bytcnt = Txpos += n;
  1758.         if (e == ZCRCW)
  1759.             goto waitack;
  1760. #ifdef READCHECK
  1761.         /*
  1762.          * If the reverse channel can be tested for data, this logic may be
  1763.          * used to detect error packets sent by the receiver, in place of
  1764.          * setjmp/longjmp rdchk(fd) returns non 0 if a character is available
  1765.          */
  1766.         while ( rdchk(0) )
  1767.         {
  1768. #ifdef EATSIT
  1769.             switch (checked)
  1770. #else
  1771.             switch ( readline(1) )
  1772. #endif
  1773.             {
  1774.                 case CAN:
  1775.                 case ZPAD:
  1776.                     c = getinsync(1);
  1777.                     if (c == ZACK)
  1778.                         break;
  1779. #ifndef    __TOWNS__
  1780. #    ifdef TCFLSH
  1781.                     ioctl(0, TCFLSH, 1);
  1782. #    endif
  1783. #endif
  1784.                     /* zcrce - dinna wanna starta ping-pong game */
  1785.                     zsdata(txbuf, 0, ZCRCE);
  1786.                     goto gotack;
  1787.                 case XOFF:        /* Wait a while for an XON */
  1788.                 case XOFF | 0200:
  1789.                     readline(100);
  1790.                 default:
  1791.                     ++junkcount;
  1792.             }
  1793.         }
  1794. #endif                            /* READCHECK */
  1795.         if (Txwindow)
  1796.         {
  1797.             while ((tcount = (Txpos - Lrxpos)) >= Txwindow)
  1798.             {
  1799.                 vfile("%ld window >= %u", tcount, Txwindow);
  1800.                 if (e != ZCRCQ)
  1801.                     zsdata(txbuf, 0, e = ZCRCQ);
  1802.                 c = getinsync(1);
  1803.                 if (c != ZACK)
  1804.                 {
  1805. #ifndef    __TOWNS__
  1806. #ifdef TCFLSH
  1807.                     ioctl(0, TCFLSH, 1);
  1808. #endif
  1809. #endif
  1810.                     zsdata(txbuf, 0, ZCRCE);
  1811.                     goto gotack;
  1812.                 }
  1813.             }
  1814.             vfile("window = %ld", tcount);
  1815.         }
  1816.     } while (!Eofseen);
  1817. #ifndef    __TOWNS__
  1818.     if (!Fromcu)
  1819.         signal(SIGINT, SIG_IGN);
  1820. #else
  1821.     if (!Fromcu)
  1822.     {
  1823.         SIGNAL(SIGINT, SIG_IGN);
  1824.         CtrlX = FALSE;
  1825.     }
  1826. #endif
  1827.  
  1828.     for (;;)
  1829.     {
  1830.         stohdr(Txpos);
  1831.         zsbhdr(4, ZEOF, Txhdr);
  1832.         switch (getinsync(0))
  1833.         {
  1834.             case ZACK:
  1835.                 continue;
  1836.             case ZRPOS:
  1837.                 goto somemore;
  1838.             case ZRINIT:
  1839.                 FM_fclose(in);    in = NULL;
  1840.                 return OK;
  1841.             case ZSKIP:
  1842.                 FM_fclose(in);    in = NULL;
  1843.                 sprintf(endmsg, "File skipped by receiver request");
  1844.                 return c;
  1845.             default:
  1846.                 sprintf(endmsg, "Got %d trying to send end of file", c);
  1847.                 FM_fclose(in);    in = NULL;
  1848.                 return ERROR;
  1849.         }
  1850.     }
  1851. }
  1852.  
  1853. /*
  1854.  * Respond to receiver's complaint, get back in sync with receiver
  1855.  */
  1856. static    int        getinsync(int flag)
  1857. {
  1858.     register    c;
  1859.  
  1860. #ifdef    DEBUG
  1861.     USR_fprintf(stderr,"getinsync(int %d)\n", flag );
  1862. #endif
  1863.     for (;;)
  1864.     {
  1865.         if (Test)
  1866.         {
  1867.             RS_puts(RsPort,"\r\n\n\n***** Signal Caught *****\r\n");
  1868.             Rxpos = 0;
  1869.             c = ZRPOS;
  1870.         } else
  1871.             c = zgethdr(Rxhdr, 0);
  1872.         switch (c)
  1873.         {
  1874.             case ZCAN:
  1875.             case ZABORT:
  1876.             case ZFIN:
  1877.             case TIMEOUT:
  1878.                 sprintf(endmsg, "Got %s sending data", frametypes[c + FTOFFSET]);
  1879.                 return ERROR;
  1880.             case ZRPOS:
  1881.                 /* ************************************* */
  1882.                 /* If sending to a buffered modem, you    */
  1883.                 /* might send a break at this point to */
  1884.                 /* dump the modem's buffer.         */
  1885.                 clearerr(in);    /* In case file EOF seen */
  1886.                 if (fseek(in, Rxpos, 0))
  1887.                     return ERROR;
  1888.                 Eofseen = 0;
  1889.                 bytcnt = Lrxpos = Txpos = Rxpos;
  1890.                 if (Lastsync == Rxpos)
  1891.                 {
  1892. #ifdef    DEBUG
  1893.                     if (++Beenhereb4 > 32)
  1894. #else
  1895.                     if (++Beenhereb4 > 12)
  1896. #endif
  1897.                     {
  1898.                         sprintf(endmsg, "Can't send block");
  1899.                         return ERROR;
  1900.                     }
  1901.                     if (Beenhereb4 > 4)
  1902.                     {
  1903.                         if (blklen > 32)
  1904.                             blklen /= 2;
  1905.                     }
  1906.                 }
  1907.                 Lastsync = Rxpos;
  1908.                 return c;
  1909.             case ZACK:
  1910.                 Lrxpos = Rxpos;
  1911.                 if (flag || Txpos == Rxpos)
  1912.                     return ZACK;
  1913.                 continue;
  1914.             case ZRINIT:
  1915.                 return c;
  1916.             case ZSKIP:
  1917.                 sprintf(endmsg, "File skipped by receiver request");
  1918.                 return c;
  1919.             case ERROR:
  1920.             default:
  1921.                 zsbhdr(4, ZNAK, Txhdr);
  1922.                 continue;
  1923.         }
  1924.     }
  1925. }
  1926.  
  1927.  
  1928. /* Say "bibi" to the receiver, try to do it cleanly */
  1929. static    void    saybibi(void)
  1930. {
  1931.     for (;;)
  1932.     {
  1933.         stohdr(0L);             /* CAF Was zsbhdr - minor change */
  1934.         zshhdr(4, ZFIN, Txhdr); /* to make debugging easier */
  1935.         switch (zgethdr(Rxhdr, 0))
  1936.         {
  1937.             case ZFIN:
  1938.                 sendline('O');
  1939.                 sendline('O');
  1940.                 flushmo();
  1941.             case ZCAN:
  1942.             case TIMEOUT:
  1943.                 return;
  1944.         }
  1945.     }
  1946. }
  1947.  
  1948. /* Local screen character display function */
  1949. static    void    bttyout(int c)
  1950. {
  1951.     if (Verbose)
  1952.         USR_fputc(c, stderr);
  1953. }
  1954.  
  1955. /* Send command and related info */
  1956. static    int        zsendcmd(char *buf, int blen)
  1957. {
  1958.     register    c;
  1959.     long        cmdnum;
  1960.  
  1961. #ifdef    DEBUG
  1962.     vfile("zsendcmd()");
  1963. #endif
  1964. #ifdef    __HIGHC__
  1965.     cmdnum = _getpid();
  1966. #else
  1967.     cmdnum = getpid();
  1968. #endif
  1969.  
  1970.     errors = 0;
  1971.     for (;;)
  1972.     {
  1973.         stohdr(cmdnum);
  1974.         Txhdr[ZF0] = Cmdack1;
  1975.         zsbhdr(4, ZCOMMAND, Txhdr);
  1976.         zsdata(buf, blen, ZCRCW);
  1977.       listen:
  1978.         Rxtimeout = 100;        /* Ten second wait for resp. */
  1979.         Usevhdrs = 0;            /* Allow rx to send fixed len headers */
  1980.         c = zgethdr(Rxhdr, 1);
  1981.  
  1982.         switch (c)
  1983.         {
  1984.             case ZRINIT:
  1985.                 goto listen;    /* CAF 8-21-87 */
  1986.             case ERROR:
  1987.             case GCOUNT:
  1988.             case TIMEOUT:
  1989.                 if (++errors > Cmdtries)
  1990.                     return ERROR;
  1991.                 continue;
  1992.             case ZCAN:
  1993.             case ZABORT:
  1994.             case ZFIN:
  1995.             case ZSKIP:
  1996.             case ZRPOS:
  1997.                 return ERROR;
  1998.             default:
  1999.                 if (++errors > 20)
  2000.                     return ERROR;
  2001.                 continue;
  2002.             case ZCOMPL:
  2003.                 Exitcode = Rxpos;
  2004.                 saybibi();
  2005.                 return OK;
  2006.             case ZRQINIT:
  2007.                 vfile("******** RZ *******");
  2008. #ifndef    __TOWNS__
  2009.                 system("rz");
  2010. #endif
  2011.                 vfile("******** SZ *******");
  2012.                 goto listen;
  2013.         }
  2014.     }
  2015. }
  2016.  
  2017. /*
  2018.  * If called as sb use YMODEM protocol
  2019.  */
  2020. static    void    chkinvok(char *s)
  2021. {
  2022.     register char *p;
  2023.  
  2024.     p = s;
  2025.     while (*p == '-')
  2026.         s = ++p;
  2027.     while (*p)
  2028.         if (*p++ == '/')
  2029.             s = p;
  2030.     if (*s == 'v')
  2031.     {
  2032.         Verbose = 1;
  2033.         ++s;
  2034.     }
  2035.     Progname = s;
  2036.     if (s[0] == 's' && s[1] == 'b')
  2037.     {
  2038.         Nozmodem = TRUE;
  2039.         blklen = 1024;
  2040.     }
  2041.     if (s[0] == 's' && s[1] == 'x')
  2042.     {
  2043.         Modem2 = TRUE;
  2044.     }
  2045. }
  2046.  
  2047. static    void    countem(int argc, register char **argv)
  2048. {
  2049.     struct stat f;
  2050.  
  2051.     Totalleft = 0;
  2052.     Filesleft = 0;
  2053.     for ( ; --argc >= 0; ++argv)
  2054.     {
  2055.         f.st_size = -1;
  2056.         if (Verbose > 2)
  2057.         {
  2058.             USR_fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
  2059.         }
  2060. #ifdef    __TOWNS__
  2061.         if (_access(*argv, 3) >= 0 && stat(*argv, &f) >= 0)
  2062. #else
  2063.         if ( _access(*argv, 04) >= 0 && stat(*argv, &f) >= 0)
  2064. #endif
  2065.         {
  2066. #ifndef    __TOWNS__
  2067.             register    c;
  2068.             c = f.st_mode & S_IFMT;
  2069.             if (c != S_IFDIR && c != S_IFBLK)
  2070.             {
  2071. #endif
  2072.                 ++Filesleft;
  2073.                 Totalleft += f.st_size;
  2074. #ifndef    __TOWNS__
  2075.             }
  2076. #endif
  2077.         }
  2078.         if ( Verbose > 2 )
  2079.             USR_fprintf(stderr, " %ld", f.st_size);
  2080.     }
  2081.     if ( Verbose > 2 )
  2082.         USR_fprintf(stderr, "\ncountem: Total %d %ld\n",
  2083.                 Filesleft, Totalleft);
  2084. }
  2085.  
  2086. static    void    chartest(int m)
  2087. {
  2088.     register    n;
  2089.  
  2090.     mode(m);
  2091.     RS_printf(RsPort,"\r\n\nCharacter Transparency Test Mode %d\r\n", m);
  2092.     RS_printf(RsPort,"If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n");
  2093.     RS_printf(RsPort,"Hit Enter.\021");
  2094.     readline(500);
  2095.  
  2096.     for (n = 0; n < 256; ++n)
  2097.     {
  2098.         if (!(n % 8))
  2099.             RS_puts(RsPort,"\r\n");
  2100.         RS_printf(RsPort,"%02x ", n);
  2101.         sendline(n);
  2102.         flushmo();
  2103.         RS_puts(RsPort,"  ");
  2104.         if (n == 127)
  2105.         {
  2106.             RS_puts(RsPort,"Hit Enter.\021");
  2107.             readline(500);
  2108.             RS_puts(RsPort,"\r\n");
  2109.         }
  2110.     }
  2111.     RS_puts(RsPort,"\021\r\nEnter Characters, echo is in hex.\r\n");
  2112.     RS_puts(RsPort,"Hit SPACE or pause 40 seconds for exit.\r\n");
  2113.  
  2114.     while (n != TIMEOUT && n != ' ')
  2115.     {
  2116.         n = readline(400);
  2117.         RS_printf(RsPort,"%02x\r\n", n);
  2118.     }
  2119.     RS_printf(RsPort,"\r\nMode %d character transparency test ends.\r\n", m);
  2120. }
  2121.  
  2122. /* End of sz.c */
  2123.